#!/usr/bin/env python
# -*- coding:utf-8 -*-
import SocketServer
import os
import hashlib

base_dir = 'D:\\'    #指定文件基本目录,有些文件字母的开头需要转义，为了拼接时避免错误，用\\

def FileMD5(file_path):     #md5加密
    with open(file_path,"rb")as f:  #hashlib模块对文件的操作
        md5obj=hashlib.md5()
        md5obj.update(f.read())     #读取文件内容，对文件进行hash
        hash=md5obj.hexdigest()
        return hash                 #返回文件的hash值

def upload(self):
    self.request.send("upload start")   #返回给客户端上传可以开始了
    FileInfoData=self.request.recv(1024)    #接收客户端发过来的指定文件信息
    file_name,file_size = FileInfoData.split('|')   #客户端发过来的文件信息格式是：文件名|文件大小；
    self.request.send("Allow transfer.")    #回应客户端，可以传输数据了
    recv_size = 0                       #设定一个接收数据的变量，以此判断接收数据的进度
    file_path=os.path.join(base_dir,file_name)      #file_path是：完整文件路径+文件名；
    with open(file_path,'wb') as fw:               #按1024字节一次一次接收数据，写入文件；
        while True:                     #反复接收数据，直到数据接收完成
            if int(file_size) > recv_size:
                data = self.request.recv(1024)
                recv_size+=len(data)
                fw.write(data)
            else:
                break
    self.request.send("upload ok")
    myfile_md5=FileMD5(file_path)       #开始md5验证
    file_md5=self.request.recv(1024)    #接收源文件的md5值，以下是判断md5是否匹配；
    if myfile_md5==file_md5:
        print "upload ok"
        self.request.send("%s upload success" % file_name)
    else:
        os.remove(file_path)
        print "upload fail"
        self.request.send("%s upload fail" % file_name)

def download(self):
    self.request.send("download start")
    file_name=self.request.recv(1024)
    #发送文件大小
    file_path=os.path.join(base_dir,file_name)
    file_size=os.stat(file_path).st_size
    self.request.send(str(file_size))
    self.request.recv(1024)     #接收下载传输指令
    send_size=0
    with open(file_path,"rb")as fr:
        flag=True
        while flag:
            if file_size-send_size<=1024:   #未发送的数据一次就能全发完了，所以这是最后一次传输；
                data=fr.read(file_size-send_size)   #只读取最后的size就行，不用1024那么大了；
                flag=False  #应用标志位，本次发送完，结束while循环；
            else:
                data=fr.read(1024)
                send_size+=1024
            self.request.send(data)
    print self.request.recv(1024)     #防止粘包
    file_md5=FileMD5(file_path) #计算源文件md5值
    self.request.send(file_md5) #将源文件MD5发送给客户端

class NetFile(SocketServer.BaseRequestHandler):
    def handle(self):       #handle方法是BaseRequestHandler预定义方法，定义文件传输的细节；
        while True:
            instruction=self.request.recv(1024)     #接收客户端指令，是上传还是下载；
            if instruction=='upload':
                upload(self)
            elif instruction=='download':
                download(self)
            else:
                break
instance = SocketServer.ThreadingTCPServer(('127.0.0.1',9999),NetFile)
instance.serve_forever()
